Amazon CloudSearchとRDS / DynamoDBの連携を考えてみる
データベースとは?
データベースと聞いて直ぐに思い浮かべるのはリレーショナルデータベースではないでしょうか。しかし、世の中には様々な種類のデータベースが存在します。
データベースの種類例
- NoSQL:DynamoDBなど
- GraphDB:Neo4jなど
- ColumnDB:Redshiftなど
- TextSearchEngine:CloudSearchなど
それぞれのデータベースには特徴があり、他のデータベースと較べて秀でている部分があります。CloudSearchは、テキスト検索エンジンとして、文字の検索に優れています。それぞれの要素は基本的に文書として保管され、文書にはフィールドがあります。フィールドは、複数の値や長さを持つことができます。そして、文書は正規化(ノーマライズ:Normalize)されていません。リレーショナル・データベースと異なる部分は、文書内の文字に完全に一致しなかったとしても、単語の出現回数(term frequency)や、文書の特徴(document frequency)、近さ(proximity)などを評価します。利用者は、距離、人気度、重み付けなどをカスタマイズすることができ、目的に応じた検索の精度を上げることが出来ます。
今回は、CloudSearchとRDSを連携させるシナリオを考えてみたいと思います。RDSは、リレーショナル・データベースサービスです。RDBMSの特徴は、トランザクション処理に優れ、原子性や完全一致といった特徴があります。一方で、全文検索をしようとしてLike文を使うと非常に処理が重いですし、重み付けや近さなどの要素は盛り込めません。CloudSearchは、逆にトランザクションやテーブルジョインなどできません。ということで、お互いの良いところを組合せましょうということですね。もちろん、ベンダーロックインで、RDBMSのプラグインを使うって手もあります。お手軽な点は良いですが、管理やスケーリングを考えると全文検索エンジンとリレーショナル・データベースは分けたほうが良さそうです。
RDSからCloudSearchへ
それぞれを連携させて動作させる場合、マスターデータをどちらに置くかですが、これはRDSとなります。データの追加・更新・削除が直ぐに行えるためです。一方で、CloudSearchはインデックスの作成に時間が掛かりますので、RDSをマスターとしてバッチで更新を掛けるのが良いかと思います。
以下は、ローダーが1つの場合の処理イメージです。同時に更新を掛けています。RDBMSは同期処理に強いですが、CloudSearchはデータの更新が即時に反映されません。このような使い方は更新系ではなく、検索するときの構図かと思います。
次に、非同期に更新を掛ける処理イメージです。この場合は、まずデータのトランザクションをRDBMSに反映させ、次にバッチ処理として裏側でRDSからデータを取り出してCloudSearchに反映させています。結構シンプルですね。この場合は、RDSのデータを全て持ってくることになりそうですので、データが多いとCloudSearch側でインデックスの再作成のコストが大きそうです。
2つ目のLoaderの処理ですが、RDSからデータの取り出しは非常に簡単です。JDBC接続など普通のデータベース接続をしてSELECT文を実行するだけです。取り出したデータはJSON形式に変換します。そして、Apache Http Clientなどのライブラリを使ってCloudSearchにポストしましょう。
次に、もうちょっと工夫した例です。まず、RDS側で追加や更新を反映させます。その際に、追加・更新した情報をログとしてS3などに溜めておきます。CloudSearch側では、追加・更新されたレコードだけ取り出して反映させることができます。
DynamoDBからCloudSearchへ
NoSQLのサービスである、DynamoDBも考えてみたいと思います。DynamoDBは、非常に高いスループットを保証することができるサービスです。NoSQLですから、グループ化したりソートしたり、テキスト検索することは不得意です。そこで、検索にはCloudSearchを用いて、ファサット検索したり、カスタマイズされたランキングの機能を持たせましょう。
DynamoDBは、テーブル、アイテム、アトリビュートの組合せでデータを持ちます。CloudSearchでいうと、ドメイン、ドキュメント、フィールドに相当します。
DynamoDBでは、テーブル設計をする際に、ある程度の正規化を行いますので、複数のテーブルに情報が分散されます。CloudSearchは、正規化されずに、1つのドキュメントに必要な全ての情報が入る構造体です。マッピングする際に気をつけましょう。
さて、DynamoDBからCloudSearchに全てのデータをインポートが完了したとします。そして、1日に1回、DynamoDBに対して追加・更新された差分データはどのようにしましょうか。DynamoDBには現時点でバージョニングの機能がありませんので、多少工夫したいと思います。DynamoDBに対して追加・更新する際に、同じテーブル構造の空のテーブル(日付などの接尾語付き)に書き込んでおきます。そして、CloudSearchに反映するタイミングで差分テーブルから反映をさせます。これによって、全データを入れなおす必要がなくなり、更新も早く終わります。
まとめ
今回は、データベースにはいろんな種類と特徴があり、どれかひとつを選んで使うのではなく、特性を活かして組合せて使いましょうということをご紹介しました。また、トランザクションに強いRDBやDynamoDBをフロントに持ってきて、テキスト検索に強いけれども更新が遅いCloudSearchを裏方に持ってくることで、利用者がまさに欲しいであろう、柔軟で高速なデータベースシステムができあがることを学びました。次回は実際にコードを書いて動作を確認してみたいと思います。クラウドを使いこなすポイントは、同期か非同期かの見極めなかと感じる今日この頃です。
参考資料
Developer Guide - Searching DynamoDB Data with Amazon CloudSearch
Articles & Tutorials - Searching DynamoDB Data with Amazon CloudSearch